home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / Filezilla Server / FileZilla_Server-0_9_41.exe / source / interface / misc / BrowseForFolder.cpp next >
C/C++ Source or Header  |  2011-11-06  |  9KB  |  342 lines

  1. //////////////////////////////////////////////////////////////////////
  2. //
  3. // ShellBrowser.cpp: implementation of the CShellBrowser class.
  4. //
  5.  
  6. #include "stdafx.h"
  7. #include "BrowseForFolder.h"
  8.  
  9. #if defined(_DEBUG) && !defined(MMGR)
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif
  14.  
  15. //////////////////////////////////////////////////////////////////////
  16. //
  17. // Construction/Destruction
  18. //
  19.  
  20. CBrowseForFolder::CBrowseForFolder(const HWND hParent /*= NULL*/, const LPITEMIDLIST pidl /*= NULL*/, const int nTitleID /*= 0*/)
  21. {
  22.     m_hwnd = NULL;
  23.     SetOwner(hParent);
  24.     SetRoot(pidl);
  25.     SetTitle(nTitleID);
  26.     m_bi.lpfn = BrowseCallbackProc;
  27.     m_bi.lParam = reinterpret_cast<long>(this);
  28.     m_bi.pszDisplayName = m_szSelected;
  29.     m_szSelected[0] = 0;
  30. }
  31.  
  32. CBrowseForFolder::CBrowseForFolder(const HWND hParent, const LPITEMIDLIST pidl, const CString& strTitle)
  33. {
  34.     m_hwnd = NULL;
  35.     SetOwner(hParent);
  36.     SetRoot(pidl);
  37.     SetTitle(strTitle);
  38.     m_bi.lpfn = BrowseCallbackProc;
  39.     m_bi.lParam = reinterpret_cast<long>(this);
  40.     m_bi.pszDisplayName = m_szSelected;
  41.     m_szSelected[0] = 0;
  42. }
  43.  
  44. CBrowseForFolder::~CBrowseForFolder()
  45. {
  46.  
  47. }
  48.  
  49. //////////////////////////////////////////////////////////////////////
  50. //
  51. // Implementation
  52. //
  53.  
  54. void CBrowseForFolder::SetOwner(const HWND hwndOwner)
  55. {
  56.     if (m_hwnd != NULL)
  57.         return;
  58.  
  59.     m_bi.hwndOwner = hwndOwner;
  60. }
  61.  
  62. void CBrowseForFolder::SetRoot(const LPITEMIDLIST pidl)
  63. {
  64.     if (m_hwnd != NULL)
  65.         return;
  66.  
  67.     m_bi.pidlRoot = pidl;
  68. }
  69.  
  70. CString CBrowseForFolder::GetTitle() const
  71. {
  72.     return m_bi.lpszTitle;
  73. }
  74.  
  75. void CBrowseForFolder::SetTitle(const CString& strTitle)
  76. {
  77.     if (m_hwnd != NULL)
  78.         return;
  79.  
  80.     m_pchTitle=strTitle;
  81.     m_bi.lpszTitle = m_pchTitle;
  82. }
  83.  
  84. bool CBrowseForFolder::SetTitle(const int nTitle)
  85. {
  86.     if (nTitle <= 0)
  87.         return false;
  88.  
  89.     CString strTitle;
  90.     if(!strTitle.LoadString(static_cast<size_t>(nTitle)))
  91.     {
  92.         return false;
  93.     }
  94.     SetTitle(strTitle);
  95.     return true;
  96. }
  97.  
  98. void CBrowseForFolder::SetFlags(const UINT ulFlags)
  99. {
  100.     if (m_hwnd != NULL)
  101.         return;
  102.  
  103.     m_bi.ulFlags = ulFlags;
  104. }
  105.  
  106. CString CBrowseForFolder::GetSelectedFolder() const
  107. {
  108.     return m_szSelected;
  109. }
  110.  
  111. bool CBrowseForFolder::SelectFolder()
  112. {
  113.     bool bRet = false;
  114.  
  115.     LPITEMIDLIST pidl;
  116.     if ((pidl = ::SHBrowseForFolder(&m_bi)) != NULL)
  117.     {
  118.         m_strPath.Empty();
  119.         if (::SHGetPathFromIDList(pidl, m_szSelected))
  120.         {
  121.             bRet = true;
  122.             m_strPath = m_szSelected;
  123.         }
  124.  
  125.         LPMALLOC pMalloc;
  126.         //Retrieve a pointer to the shell's IMalloc interface
  127.         if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  128.         {
  129.             // free the PIDL that SHBrowseForFolder returned to us.
  130.             pMalloc->Free(pidl);
  131.             // release the shell's IMalloc interface
  132.             (void)pMalloc->Release();
  133.         }
  134.     }
  135.     m_hwnd = NULL;
  136.  
  137.     return bRet;
  138. }
  139.  
  140. void CBrowseForFolder::OnInit() const
  141. {
  142.  
  143. }
  144.  
  145. void CBrowseForFolder::OnSelChanged(const LPITEMIDLIST pidl) const
  146. {
  147.     (void)pidl;
  148. }
  149.  
  150. void CBrowseForFolder::EnableOK(const bool bEnable) const
  151. {
  152.     if (m_hwnd == NULL)
  153.         return;
  154.  
  155.     (void)SendMessage(m_hwnd, BFFM_ENABLEOK, NULL, static_cast<WPARAM>(bEnable));
  156. }
  157.  
  158. void CBrowseForFolder::SetSelection(const LPITEMIDLIST pidl) const
  159. {
  160.     if (m_hwnd == NULL)
  161.         return;
  162.  
  163.     (void)SendMessage(m_hwnd, BFFM_SETSELECTION, FALSE, reinterpret_cast<long>(pidl));
  164. }
  165.  
  166. void CBrowseForFolder::SetSelection(const CString& strPath) const
  167. {
  168.     if (m_hwnd == NULL)
  169.         return;
  170.  
  171.     (void)SendMessage(m_hwnd, BFFM_SETSELECTION, TRUE, reinterpret_cast<long>(LPCTSTR(strPath)));
  172. }
  173.  
  174. void CBrowseForFolder::SetStatusText(const CString& strText) const
  175. {
  176.     if (m_hwnd == NULL)
  177.         return;
  178.  
  179.     CString oPathString = FormatLongPath(strText);
  180.  
  181.     (void)SendMessage(m_hwnd, BFFM_SETSTATUSTEXT, NULL,
  182.         reinterpret_cast<long>(LPCTSTR(oPathString/*strText*/)));
  183. }
  184.  
  185. int __stdcall CBrowseForFolder::BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  186. {
  187.     CBrowseForFolder* pbff = reinterpret_cast<CBrowseForFolder*>(lpData);
  188.     pbff->m_hwnd = hwnd;
  189.     if (uMsg == BFFM_INITIALIZED)
  190.         pbff->OnInit();
  191.     else if (uMsg == BFFM_SELCHANGED)
  192.         pbff->OnSelChanged(reinterpret_cast<LPITEMIDLIST>(lParam));
  193.     
  194.     return 0;
  195. }
  196.  
  197. /*************************
  198. 3. Finally, the body of FormatLongPath looks like that:
  199. **************************/
  200.  
  201. CString CBrowseForFolder::FormatLongPath(CString oLongPath) const
  202. {
  203.     //will be passed instead of original
  204.     CString oModifString( oLongPath );
  205.  
  206.     //will be used to get measurements
  207.     CWnd oWnd;
  208.  
  209.     if( !oModifString.IsEmpty() && IsWindow(m_hwnd) && oWnd.Attach(m_hwnd) )
  210.     {
  211.         //margins must be considered
  212.         RECT Rect = { 0, 0, 7, 0 };    //my lucky guess the margin would be seven units. It used to be 7 in resource editor, so why not here?
  213.         int nMargin = MapDialogRect( m_hwnd, &Rect ) ? Rect.right : 20;    //convert into pixels then
  214.         
  215.         //measure the width first
  216.         CRect oClientRect;
  217.         oWnd.GetClientRect( &oClientRect );
  218.         oClientRect.NormalizeRect();
  219.         int nMaxTextWidth = oClientRect.Width() - nMargin*2;
  220.         
  221.         CClientDC oClientDC(&oWnd);
  222.  
  223.         //trying to determine the system metrix to create apropriate fonts for measurement
  224.         NONCLIENTMETRICS NonClientMetrics;
  225.         
  226.         NonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS);
  227.         
  228.         BOOL bSystemMetrics = SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 
  229.             NonClientMetrics.cbSize, 
  230.             &NonClientMetrics,
  231.             0 );
  232.  
  233.         if( bSystemMetrics )
  234.         {
  235.             CFont oMessageFont;//lets create the fonts same as the selected Message Font on the Display/Appearance tab
  236.  
  237.             if( oMessageFont.CreateFontIndirect(&NonClientMetrics.lfMessageFont) )
  238.             {
  239.                 oClientDC.SelectObject( &oMessageFont );
  240.             }
  241.         }
  242.         else
  243.         {
  244.             oClientDC.SelectStockObject( SYSTEM_FONT );    //it MUST NOT happen, but in case...
  245.         }
  246.         
  247.         //measure the actual text width
  248.         int nTextWidth = oClientDC.GetTextExtent( oModifString ).cx;
  249.  
  250.         //to check whether it's correct uncoment below and change directory few times...
  251.         //oClientDC.SelectStockObject( BLACK_PEN );
  252.         //oClientDC.Rectangle( 0, 0, nMargin, nMargin*5 );
  253.         //oClientDC.Rectangle( nMaxTextWidth+nMargin, 0, oClientRect.Width(), nMargin*5 );
  254.         //oClientDC.Rectangle( nMargin, 0, nMaxTextWidth+nMargin, nMargin );
  255.         //oClientDC.TextOut( nMargin, 0, oModifString );
  256.         
  257.         //after all this measurements time to do the real job
  258.         if( nTextWidth > nMaxTextWidth )
  259.         {
  260.             int nRootDirIndex, nLastDirIndex;
  261.  
  262.             //this is the testing line:
  263.             //oModifString = "\\\\computer_name\\dir1\\subdir1" + oModifString.Right(oModifString.GetLength() - 2 );
  264.  
  265.             nRootDirIndex = oModifString.Find( '\\' );
  266.             nLastDirIndex = oModifString.ReverseFind( '\\' );
  267.  
  268.             if( nRootDirIndex == 0 )    //we have to deal with the network 'drive', which would look like that: \\computer_name\dir1\subdir1
  269.             {
  270.                 nRootDirIndex = oModifString.Find( '\\', nRootDirIndex+1 );
  271.                 if( nRootDirIndex != -1 )
  272.                 {
  273.                     nRootDirIndex = oModifString.Find( '\\', nRootDirIndex+1 );
  274.                 }
  275.             }
  276.  
  277.             if( nRootDirIndex != -1 && nLastDirIndex != -1 )
  278.             {
  279.                 nRootDirIndex += 1;    //increase for the tactical reasons
  280.  
  281.                 CString oDottedText( "..." );//this three dots will be used to indicate the cut part of the path
  282.  
  283.                 CString oRootDirectory;     //this can be cut as the last one
  284.                 CString oMidDirectoryPart;    //we will try to shorten this part first
  285.                 CString oLastDirectory;     //and then, if still too long we'll cut this one
  286.                 
  287.                 oRootDirectory =    oModifString.Left( nRootDirIndex );
  288.                 oMidDirectoryPart =    oModifString.Mid( nRootDirIndex, nLastDirIndex - nRootDirIndex );
  289.                 oLastDirectory =    oModifString.Mid( nLastDirIndex );
  290.                 
  291.                 while( nTextWidth > nMaxTextWidth )
  292.                 {
  293.                     int nMidPartLenght = oMidDirectoryPart.GetLength();
  294.  
  295.                     oModifString = oRootDirectory + oMidDirectoryPart + oDottedText + oLastDirectory;
  296.  
  297.                     //measure the actual text width again
  298.                     nTextWidth = oClientDC.GetTextExtent( oModifString ).cx;
  299.                     
  300.                     if( nMidPartLenght > 0 )
  301.                     {
  302.                         //prepare for the next loop (if any)
  303.                         oMidDirectoryPart = oMidDirectoryPart.Left(oMidDirectoryPart.GetLength() - 1 );
  304.                     }
  305.                     else
  306.                     {
  307.                         int nLastDirectoryLenght = oLastDirectory.GetLength();
  308.                         
  309.                         if( nLastDirectoryLenght > 0 )
  310.                         {
  311.                             //prepare for the next loop (if any)
  312.                             oLastDirectory = oLastDirectory.Right(oLastDirectory.GetLength() - 1 );
  313.                         }
  314.                         else
  315.                         {
  316.                             //should not come here, what size of the fonts are you using?!
  317.                             //anyway, we will do different now, cutting from the end...
  318.                             int nRootDirectoryLenght = oRootDirectory.GetLength();
  319.  
  320.                             if( nRootDirectoryLenght > 0 )
  321.                             {
  322.                                 oRootDirectory = oRootDirectory.Left(oRootDirectory.GetLength() - 1 );
  323.                             }
  324.                             else
  325.                             {
  326.                                 TRACE0( "Mayday, Mayday!!!\n" );
  327.                                 oModifString = oLongPath;
  328.                                 //something wrong, give me a...
  329.                                 break;
  330.                             }
  331.                         }
  332.                     }
  333.                 }//end while
  334.             }
  335.         }
  336.  
  337.         oWnd.Detach();
  338.     }
  339.  
  340.     return oModifString;
  341. }
  342.